package com.relytosoft.mizar.analyze.common.filter;

import cn.hutool.core.date.DateUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Jierry
 * @version 2022/5/11.
 */
@Aspect
@Component
@ConditionalOnExpression("${relytosoft.mizar.analyze.apilog.enabled:true}")
public class ApiAspect {

    private static final Logger log = LoggerFactory.getLogger(ApiAspect.class);

    @Around("execution(* com.relytosoft.mizar.analyze.*.*.controller.*.*(..))")
    private Object controllerAspect(final ProceedingJoinPoint pjp) throws Throwable {
        final long startTime = System.currentTimeMillis();
        final HttpServletRequest request = this.getRequest();
        final String uri = (request != null) ? request.getRequestURI() : "";
        log.info("controllerAspect startTime:{}|url:{}|start|request: {}", DateUtil.date(startTime), uri, this.getParamsMap(request));
        final Object response = pjp.proceed();
        final long endTime = System.currentTimeMillis();
        log.info("controllerAspect end:{}|url:{}|cost Time {} ms end", DateUtil.date(endTime), uri, endTime - startTime);
        return response;
    }

    private HttpServletRequest getRequest() {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        return (ra == null) ? null : ((ServletRequestAttributes) ra).getRequest();
    }

    private Map<String, String> getParamsMap(final HttpServletRequest request) {
        final Map<String, String> map = new HashMap<>();
        if (request == null || request.getParameterMap() == null) {
            return map;
        }
        final Map<String, String[]> parameterMap = request.getParameterMap();
        final String[] value = new String[1];
        parameterMap.forEach((key, values) -> {
            value[0] = ((values == null) ? "" : String.join(",", values));
            map.put(key, value[0]);
        });
        return map;
    }
}
